﻿using System;
using System.Text;
using GeoAPI.Geometries;
using NetTopologySuite.Algorithm;

namespace NetTopologySuite.Operation.Distance
{
	public class FacetSequence
	{
		public FacetSequence(ICoordinateSequence pts, int start, int end)
		{
			this._pts = pts;
			this._start = start;
			this._end = end;
		}

		public FacetSequence(ICoordinateSequence pts, int index)
		{
			this._pts = pts;
			this._start = index;
			this._end = index + 1;
		}

		public Envelope Envelope
		{
			get
			{
				Envelope envelope = new Envelope();
				for (int i = this._start; i < this._end; i++)
				{
					envelope.ExpandToInclude(this._pts.GetX(i), this._pts.GetY(i));
				}
				return envelope;
			}
		}

		public int Count
		{
			get
			{
				return this._end - this._start;
			}
		}

		public Coordinate GetCoordinate(int index)
		{
			return this._pts.GetCoordinate(this._start + index);
		}

		public bool IsPoint
		{
			get
			{
				return this._end - this._start == 1;
			}
		}

		public double Distance(FacetSequence facetSeq)
		{
			bool isPoint = this.IsPoint;
			bool isPoint2 = facetSeq.IsPoint;
			if (isPoint && isPoint2)
			{
				this._pts.GetCoordinate(this._start, this._pt);
				facetSeq._pts.GetCoordinate(facetSeq._start, this._seqPt);
				return this._pt.Distance(this._seqPt);
			}
			if (isPoint)
			{
				this._pts.GetCoordinate(this._start, this._pt);
				return FacetSequence.ComputePointLineDistance(this._pt, facetSeq);
			}
			if (isPoint2)
			{
				facetSeq._pts.GetCoordinate(facetSeq._start, this._seqPt);
				return FacetSequence.ComputePointLineDistance(this._seqPt, this);
			}
			return this.ComputeLineLineDistance(facetSeq);
		}

		private double ComputeLineLineDistance(FacetSequence facetSeq)
		{
			double num = double.MaxValue;
			Coordinate coordinate = new Coordinate();
			Coordinate coordinate2 = new Coordinate();
			Coordinate coordinate3 = new Coordinate();
			Coordinate coordinate4 = new Coordinate();
			for (int i = this._start; i < this._end - 1; i++)
			{
				for (int j = facetSeq._start; j < facetSeq._end - 1; j++)
				{
					this._pts.GetCoordinate(i, coordinate);
					this._pts.GetCoordinate(i + 1, coordinate2);
					facetSeq._pts.GetCoordinate(j, coordinate3);
					facetSeq._pts.GetCoordinate(j + 1, coordinate4);
					double num2 = CGAlgorithms.DistanceLineLine(coordinate, coordinate2, coordinate3, coordinate4);
					if (num2 == 0.0)
					{
						return 0.0;
					}
					if (num2 < num)
					{
						num = num2;
					}
				}
			}
			return num;
		}

		private static double ComputePointLineDistance(Coordinate pt, FacetSequence facetSeq)
		{
			double num = double.MaxValue;
			Coordinate coordinate = new Coordinate();
			Coordinate coordinate2 = new Coordinate();
			for (int i = facetSeq._start; i < facetSeq._end - 1; i++)
			{
				facetSeq._pts.GetCoordinate(i, coordinate);
				facetSeq._pts.GetCoordinate(i + 1, coordinate2);
				double num2 = CGAlgorithms.DistancePointLine(pt, coordinate, coordinate2);
				if (num2 == 0.0)
				{
					return 0.0;
				}
				if (num2 < num)
				{
					num = num2;
				}
			}
			return num;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(this.IsPoint ? "LINESTRING ( " : "POINT (");
			Coordinate coordinate = new Coordinate();
			for (int i = this._start; i < this._end; i++)
			{
				if (i > this._start)
				{
					stringBuilder.Append(", ");
				}
				this._pts.GetCoordinate(i, coordinate);
				stringBuilder.Append(coordinate.X + " " + coordinate.Y);
			}
			stringBuilder.Append(" )");
			return stringBuilder.ToString();
		}

		private readonly ICoordinateSequence _pts;

		private readonly int _start;

		private readonly int _end;

		private readonly Coordinate _pt = new Coordinate();

		private readonly Coordinate _seqPt = new Coordinate();
	}
}
